package com.daffodil.storage.controller;

import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.util.unit.DataSize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.daffodil.storage.constant.StorageConstant;
import com.daffodil.storage.model.JsonResult;
import com.daffodil.storage.model.MediaAllow;
import com.daffodil.storage.model.MediaMimetype;
import com.daffodil.storage.model.Page;
import com.daffodil.storage.model.StorageRequest;
import com.daffodil.storage.model.StorageResult;
import com.daffodil.storage.model.TableResult;
import com.daffodil.storage.service.IStorageService;
import com.daffodil.storage.util.StorageUtils;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import springfox.documentation.annotations.ApiIgnore;

/**
 * 
 * @author yweijian
 * @date 2022年12月8日
 * @version 2.0.0
 * @description
 */
@Api(value = "对象存储管理", tags = "对象存储管理")
@RestController
@RequestMapping(StorageConstant.API_CONTENT_PATH)
public class StorageController {

    @Value("${spring.servlet.multipart.max-file-size:50MB}")
    private String maxFileSize;

    @Autowired
    private IStorageService storageService;

    @ApiOperation(value = "上传对象（multipart/form-data方式上传）", notes = "/upload 适用于上传50MB以下的任意存储对象，存在一定的安全风险。")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:object:upload")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "上传", label = "UPLOAD"))
    @PostMapping(value = "/upload", headers = "content-type=multipart/form-data")
    public JsonResult upload(@ApiParam(name = "folder", value = "业务文件夹名称") @RequestPart("folder") @Nullable String folder,
            @ApiParam(name = "key", value = "对象存储键值，如未指定则按应用日期格式默认规则存储") @RequestPart("key") @Nullable String key,
            @ApiParam(name = "file", value = "资源文件") @RequestPart("file") MultipartFile multipartFile,
            @ApiIgnore HttpServletRequest request) {

        Map<String, String> metadata = StorageUtils.getParameterMap(request).toSingleValueMap();
        MediaAllow allow = MediaAllow.builder().min(0L).max(DataSize.parse(maxFileSize).toBytes()).build();

        StorageRequest storageRequest = StorageRequest.builder().request(request).allow(allow).folder(folder).key(key)
                .metadata(metadata).file(multipartFile).build();

        StorageResult result = storageService.upolad(storageRequest);
        return JsonResult.success(result);
    }

    @ApiOperation(value = "远程抓取对象", notes = "/upload 适用于抓取50MB以下的远程图片、压缩文件、文档文件，存在一定的安全风险。")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:object:upload")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "上传", label = "UPLOAD"))
    @PostMapping(value = "/upload", headers = "content-type=application/json")
    public JsonResult upload(@RequestBody StorageRequest storageRequest, @ApiIgnore HttpServletRequest request) {

        MediaAllow allow = MediaAllow.builder().suffixs(MediaMimetype.ALLEXT)
                .contentTypes(MediaMimetype.getInstance().getMimetypes(MediaMimetype.ALLEXT)).min(0L)
                .max(DataSize.parse(maxFileSize).toBytes()).build();

        storageRequest.setRequest(request);
        storageRequest.setAllow(allow);

        StorageResult result = storageService.upolad(storageRequest);
        return JsonResult.success(result);
    }

    @ApiOperation(value = "上传图片（multipart/form-data方式上传）", notes = "/image/upload 适用于上传50MB以下的图片文件。")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:image:upload")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "上传", label = "UPLOAD"))
    @PostMapping(value = "/image/upload", headers = "content-type=multipart/form-data")
    public JsonResult image(@ApiParam(name = "folder", value = "业务文件夹名称") @RequestPart("folder") @Nullable String folder,
            @ApiParam(name = "key", value = "对象存储键值，如未指定则按应用日期格式默认规则存储") @RequestPart("key") @Nullable String key,
            @ApiParam(name = "file", value = "资源文件") @RequestPart("file") MultipartFile multipartFile,
            @ApiIgnore HttpServletRequest request) {

        Map<String, String> metadata = StorageUtils.getParameterMap(request).toSingleValueMap();
        MediaAllow allow = MediaAllow.builder().suffixs(MediaMimetype.IMGS)
                .contentTypes(MediaMimetype.getInstance().getMimetypes(MediaMimetype.IMGS)).min(0L)
                .max(DataSize.parse(maxFileSize).toBytes()).build();

        StorageRequest storageRequest = StorageRequest.builder().request(request).allow(allow).folder(folder).key(key)
                .metadata(metadata).file(multipartFile).build();

        StorageResult result = storageService.upolad(storageRequest);
        return JsonResult.success(result);
    }

    @ApiOperation(value = "远程抓取图片", notes = "/image/upload 适用于抓取50MB以下的远程图片。")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:image:upload")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "上传", label = "UPLOAD"))
    @PostMapping(value = "/image/upload", headers = "content-type=application/json")
    public JsonResult image(@RequestBody StorageRequest storageRequest, @ApiIgnore HttpServletRequest request) {

        MediaAllow allow = MediaAllow.builder().suffixs(MediaMimetype.IMGS)
                .contentTypes(MediaMimetype.getInstance().getMimetypes(MediaMimetype.IMGS)).min(0L)
                .max(DataSize.parse(maxFileSize).toBytes()).build();

        storageRequest.setRequest(request);
        storageRequest.setAllow(allow);

        StorageResult result = storageService.upolad(storageRequest);
        return JsonResult.success(result);
    }

    @ApiOperation(value = "上传对象（binary方式单文件上传）", notes = "/binary/upload 适用上传以下的任意存储对象，存在一定的安全风险。")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:binary:upload")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "上传", label = "UPLOAD"))
    @PostMapping(value = "/binary/upload")
    public JsonResult binary(@ApiParam(name = "folder", value = "业务文件夹名称") @Nullable String folder,
            @ApiParam(name = "key", value = "对象存储键值，如未指定则按应用日期格式默认规则存储") @Nullable String key,
            @ApiIgnore HttpServletRequest request) {

        MediaAllow allow = MediaAllow.builder().min(0L).max(DataSize.parse(maxFileSize).toBytes()).build();

        StorageRequest storageRequest = StorageRequest.builder().request(request).allow(allow).folder(folder).key(key)
                .build();

        StorageResult result = storageService.upolad(storageRequest);
        return JsonResult.success(result);
    }

    @ApiOperation("分页查询对象")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:object:list")
    @GetMapping("/list")
    public TableResult list(@ApiParam(name = "folder", value = "业务文件夹名称") String folder,
            @ApiParam(name = "name", value = "对象名称") String name, Page page, @ApiIgnore HttpServletRequest request) {

        List<StorageResult> list = storageService.list(folder, name, page);
        return TableResult.success(list, page);
    }

    @ApiOperation("下载对象")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:object:download")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "下载", label = "DOWNLOAD"))
    @GetMapping("/download")
    public void download(@ApiParam(name = "key", value = "对象键值") String key, @ApiIgnore HttpServletResponse response) {
        storageService.download(key, response);
    }

    @ApiOperation("删除对象")
    @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "登录授权令牌 Bearer token", paramType = "header", required = true)
    //@AuthPermission("storage:object:remove")
    //@OperLog(title = "对象存储管理", business = @OperBusiness(name = "删除", label = "DELETE", remark = "删除对象存储"))
    @PostMapping("/remove")
    public JsonResult remove(@ApiParam(name = "keys", value = "对象键值") @RequestBody String[] keys, @ApiIgnore HttpServletRequest request) {
        for (String key : keys) {
            storageService.remove(key);
        }
        return JsonResult.success();
    }
}
